﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using GL.Tools;

namespace WAD.WEB.AppCode.WxPay.Pay
{
    /// <summary>
    /// 支付给微信账户
    /// </summary>
    public class PayToWx
    {
        /// <summary>
        /// 证书所在路劲
        /// </summary>
        private const String CERT_PATH = "/bin/apiclient_cert.p12";

        /// <summary>
        /// 付款到微信用户
        /// </summary>
        /// <param name="openId">用户openid</param>
        /// <param name="tradeNo">订单号</param>
        /// <param name="money">付款金额</param>
        /// <returns>付款结果</returns>
        public static String Pay(String openId, String tradeNo, int money)
        {
            //绑定此商户号的公众账号appid或开放平台产品的AppID
            String mch_appid = WJXConfig.WeixinOpenConfig.APPID;

            //微信支付商户号
            String mchid = WJXConfig.WeixinOpenConfig.MCHID;

            //不可预测的随机字符串
            String nonce_str = StringHelper.Random(32);

            //商户订单号不允许重复
            String partner_trade_no = tradeNo;

            //收款用户的openid
            String openid = openId;

            //NO_CHECK：不校验真实姓名 FORCE_CHECK：强校验真实姓名（未实名认证的用户会校验失败，无法转账） OPTION_CHECK：针对已实名认证的用户才校验真实姓名（未实名认证用户不校验，可以转账成功）
            String check_name = "NO_CHECK";

            //String check_name = "OPTION_CHECK";
            //String re_user_name = "周隆权";

            //付款金额，单位为分,每次付款金额必须大于1元
            int amount = money;

            //企业付款操作说明信息.
            String desc = "提现";

            //调用接口的机器Ip地址
            String spbill_create_ip = "127.0.0.1";

            //API密钥
            String key = WJXConfig.WeixinOpenConfig.KEY;

            //api接口
            String apiUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";

            //微信商户证书所在路劲
            String certPath = HttpContext.Current.Server.MapPath(CERT_PATH);


            //拼接参数
            String qureyString = "amount=" + amount + "&check_name=" + check_name + "&desc=" + desc
                + "&mch_appid=" + mch_appid + "&mchid=" + mchid + "&nonce_str="
                + nonce_str + "&openid=" + openid + "&partner_trade_no=" + partner_trade_no
                //+ "&re_user_name=" + re_user_name
                + "&spbill_create_ip=" + spbill_create_ip + "&key=" + key;

            //生成签名
            String sign = GL.Tools.StringHelper.MD5Encrypt(qureyString).ToUpper();

            //生成xml
            String xmlInfo = "<xml><mch_appid>{0}</mch_appid><mchid>{1}</mchid><nonce_str>{2}</nonce_str><partner_trade_no>{3}</partner_trade_no><openid>{4}</openid><check_name>{5}</check_name><amount>{6}</amount><desc>{7}</desc><spbill_create_ip>{8}</spbill_create_ip><sign>{9}</sign></xml>";
            String payInfo = new StringBuilder().AppendFormat(xmlInfo, mch_appid, mchid, nonce_str, partner_trade_no, openid, check_name, amount, desc, spbill_create_ip, sign).ToString();

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl);

            request.Method = "POST";
            request.Timeout = 10 * 1000;

            //导入证书
            byte[] rawData = ReadFile(certPath);
            X509Certificate2 x509 = new X509Certificate2(rawData, mchid);
            X509Store store = new X509Store();
            store.Open(OpenFlags.MaxAllowed);
            store.Add(x509);
            store.Close();
            request.ClientCertificates.Add(x509);


            //设置POST的数据类型和长度
            request.ContentType = "text/xml";
            byte[] data = System.Text.Encoding.UTF8.GetBytes(payInfo);
            request.ContentLength = data.Length;

            //往服务器写入数据
            Stream reqStream = request.GetRequestStream();
            reqStream.Write(data, 0, data.Length);
            reqStream.Close();

            //获取服务端返回
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            //获取服务端返回数据
            StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"));
            String rs = sr.ReadToEnd().Trim();
            sr.Close();

            return rs;
        }

        /// <summary>
        /// 查询转账订单状态,根据 status 判断是否成功(SUCCESS 转账成功, FAILED 转账失败, PROCESSING 处理中)(官方文档链接：https://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3 )
        /// </summary>
        /// <param name="tradeNo">订单号</param>
        /// <returns>XML文档格式</returns>
        public static String GetTransferInfo(String tradeNo)
        {
            //绑定此商户号的公众账号appid或开放平台产品的AppID
            String appid = WJXConfig.WeixinOpenConfig.APPID;

            //微信支付商户号
            String mchid = WJXConfig.WeixinOpenConfig.MCHID;

            //不可预测的随机字符串
            String nonce_str = StringHelper.Random(32);

            //商户订单号不允许重复
            String partner_trade_no = tradeNo;

            //API密钥
            String key = WJXConfig.WeixinOpenConfig.KEY;


            //api接口
            String apiUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";

            //微信商户证书所在路劲
            String certPath = HttpContext.Current.Server.MapPath(CERT_PATH);


            //拼接参数
            String qureyString = "appid=" + appid + "&mch_id=" + mchid + "&nonce_str="
                + nonce_str + "&partner_trade_no=" + partner_trade_no + "&key=" + key;

            //生成签名
            String sign = GL.Tools.StringHelper.MD5Encrypt(qureyString).ToUpper();

            //生成xml
            String xmlInfo = "<xml><appid>{0}</appid><mch_id>{1}</mch_id><nonce_str>{2}</nonce_str><partner_trade_no>{3}</partner_trade_no><sign>{4}</sign></xml>";
            String payInfo = new StringBuilder().AppendFormat(xmlInfo, appid, mchid, nonce_str, partner_trade_no, sign).ToString();

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl);

            request.Method = "POST";
            request.Timeout = 10 * 1000;

            //导入证书
            byte[] rawData = ReadFile(certPath);
            X509Certificate2 x509 = new X509Certificate2(rawData, mchid);
            X509Store store = new X509Store();
            store.Open(OpenFlags.MaxAllowed);
            store.Add(x509);
            store.Close();
            request.ClientCertificates.Add(x509);


            //设置POST的数据类型和长度
            request.ContentType = "text/xml";
            byte[] data = System.Text.Encoding.UTF8.GetBytes(payInfo);
            request.ContentLength = data.Length;

            //往服务器写入数据
            Stream reqStream = request.GetRequestStream();
            reqStream.Write(data, 0, data.Length);
            reqStream.Close();

            //获取服务端返回
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            //获取服务端返回数据
            StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"));
            String rs = sr.ReadToEnd().Trim();
            sr.Close();

            return rs;
        }

        /// <summary>
        /// 将文件读取到字节数组
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private static byte[] ReadFile(string fileName)
        {
            FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            int size = (int)f.Length;
            byte[] data = new byte[size];
            size = f.Read(data, 0, size);
            f.Close();
            return data;
        }
    }
}